Elaborado por Ulises González

Credit Card Fraud Prediction Este conjunto de datos ofrece una variedad de atributos valiosos para un análisis exhaustivo. Contiene 555.719 instancias y 22 atributos, una combinación de tipos de datos categóricos y numéricos. Es importante destacar que el conjunto de datos está completo y no tiene valores nulos. Aquí hay un desglose de los atributos:

  • Trans_date_trans_time: Marca de tiempo de la transacción (fecha y hora).
  • Cc_num:Número único de identificación del cliente.
  • Comerciante: El comerciante involucrado en la transacción.
  • Categoría Tipo de transacción (por ejemplo, personal, cuidado de niños).
  • Amt: Monto de la transacción. Nombre: nombre del titular de la tarjeta.
  • Apellido del último titular de la tarjeta.
  • Género: Género del titular de la tarjeta.
  • Calle: Dirección postal del titular de la tarjeta.
  • Ciudad: Ciudad de residencia del titular de la tarjeta.
  • Estado: Estado de residencia del titular de la tarjeta.
  • Zip: Código postal del titular de la tarjeta.
  • Lat: Latitud de la ubicación del titular de la tarjeta.
  • Largo: Longitud de la ubicación del titular de la tarjeta.
  • City_pop: Población de la ciudad del titular de la tarjeta.
  • Puesto: puesto de trabajo del titular de la tarjeta.
  • Dob: Fecha de nacimiento del titular de la tarjeta.
  • Trans_num: Identificador único de transacción.
  • Unix_time: marca de tiempo de la transacción (formato Unix).
  • Merch_lat: Ubicación del comerciante (latitud).
  • Merch_long: Ubicación del comerciante (longitud).
  • Is_fraud:Indicador de transacción fraudulenta (1 = fraude, 0 = legítimo). Esta es la variable objetivo a efectos de clasificación.

Fuente: https://www.kaggle.com/datasets/kelvinkelue/credit-card-fraud-prediction

In [2]:
#Importando los módulos principales
In [3]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import dataprep.eda as eda
import folium
from scipy.stats import norm
In [4]:
data = pd.read_csv('https://media.githubusercontent.com/media/gonzalezulises/lfsCreditCard/main/CreditCardFraudPrediction.csv') 
# El tamaño del archivo supera los 100 megas, por lo cual configure un GIT LFS, acá el repositorio: https://github.com/gonzalezulises/lfsCreditCard.git
In [5]:
data.head(5)
Out[5]:
Unnamed: 0 trans_date_trans_time cc_num merchant category amt first last gender street ... lat long city_pop job dob trans_num unix_time merch_lat merch_long is_fraud
0 0 21/06/2020 12:14 2.291160e+15 fraud_Kirlin and Sons personal_care 2.86 Jeff Elliott M 351 Darlene Green ... 33.9659 -80.9355 333497 Mechanical engineer 19/03/1968 2da90c7d74bd46a0caf3777415b3ebd3 1371816865 33.986391 -81.200714 0
1 1 21/06/2020 12:14 3.573030e+15 fraud_Sporer-Keebler personal_care 29.84 Joanne Williams F 3638 Marsh Union ... 40.3207 -110.4360 302 Sales professional, IT 17/01/1990 324cc204407e99f51b0d6ca0055005e7 1371816873 39.450498 -109.960431 0
2 2 21/06/2020 12:14 3.598220e+15 fraud_Swaniawski, Nitzsche and Welch health_fitness 41.28 Ashley Lopez F 9333 Valentine Point ... 40.6729 -73.5365 34496 Librarian, public 21/10/1970 c81755dbbbea9d5c77f094348a7579be 1371816893 40.495810 -74.196111 0
3 3 21/06/2020 12:15 3.591920e+15 fraud_Haley Group misc_pos 60.05 Brian Williams M 32941 Krystal Mill Apt. 552 ... 28.5697 -80.8191 54767 Set designer 25/07/1987 2159175b9efe66dc301f149d3d5abf8c 1371816915 28.812398 -80.883061 0
4 4 21/06/2020 12:15 3.526830e+15 fraud_Johnston-Casper travel 3.19 Nathan Massey M 5783 Evan Roads Apt. 465 ... 44.2529 -85.0170 1126 Furniture designer 06/07/1955 57ff021bd3f328f8738bb535c302a31b 1371816917 44.959148 -85.884734 0

5 rows × 23 columns

In [6]:
data.dtypes
Out[6]:
Unnamed: 0                 int64
trans_date_trans_time     object
cc_num                   float64
merchant                  object
category                  object
amt                      float64
first                     object
last                      object
gender                    object
street                    object
city                      object
state                     object
zip                        int64
lat                      float64
long                     float64
city_pop                   int64
job                       object
dob                       object
trans_num                 object
unix_time                  int64
merch_lat                float64
merch_long               float64
is_fraud                   int64
dtype: object
In [7]:
#Para esto voy a realizar un análisis exploratorio de los datos, de manera de entender la función y sus valores asociados. Para ello 
#voy a usar dataprep (https://dataprep.ai/) que es brutal para hacer profiling
In [8]:
eda.plot( df = data)
100%|#########################################################################################################…
  0%|                                                                                                         …
Out[8]:
DataPrep.EDA Report
Dataset Statistics
Number of Variables 23
Number of Rows 555719
Missing Cells 0
Missing Cells (%) 0.0%
Duplicate Rows 0
Duplicate Rows (%) 0.0%
Total Size in Memory 492.9 MB
Average Row Size in Memory 930.0 B
Variable Types
  • Numerical: 10
  • Categorical: 13
Dataset Insights
Unnamed: 0 is uniformly distributed Uniform
lat and merch_lat have similar distributions Similar Distribution
long and merch_long have similar distributions Similar Distribution
cc_num is skewed Skewed
amt is skewed Skewed
city_pop is skewed Skewed
trans_date_trans_time has a high cardinality: 226976 distinct values High Cardinality
merchant has a high cardinality: 693 distinct values High Cardinality
first has a high cardinality: 341 distinct values High Cardinality
last has a high cardinality: 471 distinct values High Cardinality
Dataset Insights
street has a high cardinality: 924 distinct values High Cardinality
city has a high cardinality: 849 distinct values High Cardinality
job has a high cardinality: 478 distinct values High Cardinality
dob has a high cardinality: 910 distinct values High Cardinality
trans_num has a high cardinality: 555719 distinct values High Cardinality
trans_date_trans_time has constant length 16 Constant Length
gender has constant length 1 Constant Length
state has constant length 2 Constant Length
dob has constant length 10 Constant Length
trans_num has constant length 32 Constant Length
Dataset Insights
is_fraud has constant length 1 Constant Length
trans_num has all distinct values Unique
long has 555719 (100.0%) negatives Negatives
merch_long has 555719 (100.0%) negatives Negatives
  • 1
  • 2
  • 3

Number of plots per page:

Unnamed: 0
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
Column Insights
  1. Unnamed: 0 is uniformly distributed
trans_date_trans_time
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. trans_date_trans_time has a high cardinality: 226976 distinct values
  2. trans_date_trans_time has constant length 16
cc_num
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
Column Insights
  1. cc_num is skewed
merchant
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. merchant has a high cardinality: 693 distinct values
category
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
amt
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
Column Insights
  1. amt is skewed
first
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. first has a high cardinality: 341 distinct values
last
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. last has a high cardinality: 471 distinct values
gender
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. gender has constant length 1
street
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. street has a high cardinality: 924 distinct values
city
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. city has a high cardinality: 849 distinct values
state
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. state has constant length 2
zip
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
lat
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
long
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
Column Insights
  1. long has 555719 (100.0%) negatives
city_pop
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
Column Insights
  1. city_pop is skewed
job
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. job has a high cardinality: 478 distinct values
dob
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. dob has a high cardinality: 910 distinct values
  2. dob has constant length 10
trans_num
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. trans_num has a high cardinality: 555719 distinct values
  2. trans_num has constant length 32
  3. trans_num has all distinct values
unix_time
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
merch_lat
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
merch_long
'hist.bins': 50
Number of bins in the histogram
'hist.yscale': 'linear'
Y-axis scale ("linear" or "log")
'hist.color': '#aec7e8'
Color
Column Insights
  1. merch_long has 555719 (100.0%) negatives
is_fraud
'bar.bars': 10
Maximum number of bars to display
'bar.sort_descending': True
Whether to sort the bars in descending order
'bar.yscale': 'linear'
Y-axis scale ("linear" or "log")
Column Insights
  1. is_fraud has constant length 1

Preguntas de análisis

  • ¿Cuáles son las características comunes de las transacciones fraudulentas? (E.g., monto de la transacción, ubicación del comerciante, categoría de la transacción). (Para esta primera entrega voy a trabajar esta)
  • ¿Existen diferencias significativas en el comportamiento de compra entre géneros?
  • ¿Cómo varían las transacciones fraudulentas a lo largo del tiempo? (E.g., patrones diarios, mensuales o estacionales).
  • ¿Hay correlación entre la ubicación del comerciante y la frecuencia de transacciones fraudulentas?
  • ¿Cómo afecta la población de la ciudad al volumen y tipo de transacciones?

Hipótesis para probar ***A desarrollar para el proyecto final

  • Las transacciones de montos más altos tienen una mayor probabilidad de ser fraudulentas.
  • Las transacciones en ciertas categorías (como cuidado personal) son más susceptibles al fraude que otras.
  • Los clientes de ciudades con poblaciones menores experimentan una tasa más alta de transacciones fraudulentas debido a menores medidas de seguridad.
  • Las transacciones realizadas durante ciertos períodos del día son más propensas a ser fraudulentas.
  • Los datos demográficos, como la edad y el género del titular de la tarjeta, influyen en la probabilidad de fraude.

a. Histograma de Montos de Transacciones

In [9]:
df_fraude = data[data['is_fraud'] == 1 ]
In [10]:
df_fraude.head(3)
Out[10]:
Unnamed: 0 trans_date_trans_time cc_num merchant category amt first last gender street ... lat long city_pop job dob trans_num unix_time merch_lat merch_long is_fraud
1685 1685 21/06/2020 22:06 3.560730e+15 fraud_Hamill-D'Amore health_fitness 24.84 Brooke Smith F 63542 Luna Brook Apt. 012 ... 31.8599 -102.7413 23 Cytogeneticist 15/09/1969 16bf2e46c54369a8eab2214649506425 1371852399 32.575873 -102.604290 1
1767 1767 21/06/2020 22:32 6.564460e+15 fraud_Rodriguez, Yost and Jenkins misc_net 780.52 Douglas Willis M 619 Jeremy Garden Apt. 681 ... 42.5545 -90.3508 1306 Public relations officer 10/09/1958 ab4b379d2c0c9c667d46508d4e126d72 1371853942 42.461127 -91.147148 1
1781 1781 21/06/2020 22:37 6.564460e+15 fraud_Nienow PLC entertainment 620.33 Douglas Willis M 619 Jeremy Garden Apt. 681 ... 42.5545 -90.3508 1306 Public relations officer 10/09/1958 47a9987ae81d99f7832a54b29a77bf4b 1371854247 42.771834 -90.158365 1

3 rows × 23 columns

In [11]:
plt.figure(figsize=(10, 6))
plt.hist(df_fraude['amt'], bins=50, color='red', alpha=0.7)
plt.title('Distribución de Montos en Transacciones Fraudulentas')
plt.xlabel('Monto')
plt.ylabel('Frecuencia')
plt.show()
No description has been provided for this image
  • Las barras indican el número de transacciones fraudulentas que cayeron dentro de cada rango de montos. Hay una concentración muy alta de transacciones con montos bajos cerca de 0, lo que sugiere que la mayoría de las transacciones fraudulentas involucran montos pequeños.
  • La distribución tiene un sesgo hacia la izquierda (o es positivamente sesgada), con frecuencias decrecientes a medida que el monto aumenta. Esto es común en datos de transacciones financieras, donde las transacciones de montos más pequeños son mucho más numerosas que las de montos grandes.
  • Hay picos secundarios en la gráfica, por ejemplo, uno notable alrededor de 200 unidades en el eje X. Esto podría indicar montos específicos que son comúnmente utilizados en transacciones fraudulentas.
In [12]:
m = folium.Map(tiles="cartodb positron")
m.save("footprint.html")
In [13]:
df_mapa_fraude = pd.DataFrame({
    'lon': df_fraude['merch_long'],
    'lat': df_fraude['merch_lat'],
    'city': df_fraude['city'],
    'state':df_fraude['state'],
    'amt': df_fraude['amt']
})
df_mapa_fraude
Out[13]:
lon lat city state amt
1685 -102.604290 32.575873 Notrees TX 24.84
1767 -91.147148 42.461127 Benton WI 780.52
1781 -90.158365 42.771834 Benton WI 620.33
1784 -90.261595 31.204974 Denham Springs LA 1077.69
1857 -102.736390 31.315782 Notrees TX 842.65
... ... ... ... ... ...
517197 -89.911011 34.573471 Senatobia MS 1041.51
517274 -90.390612 34.091227 Senatobia MS 868.09
517341 -90.284780 34.628434 Senatobia MS 1039.42
517529 -90.401093 34.746063 Senatobia MS 289.27
517571 -90.651342 33.771462 Senatobia MS 766.38

2145 rows × 5 columns

In [14]:
# Creando un mapa base con Folium en la ubicación inicial deseada y con un nivel de zoom que se ajuste
m = folium.Map(location=[df_mapa_fraude['lat'].mean(), df_mapa_fraude['lon'].mean()], zoom_start=6)
for i in range(len(df_mapa_fraude)): #con esto añado los marcadores al mapa
    folium.Marker(
        location=[df_mapa_fraude.iloc[i]['lat'], df_mapa_fraude.iloc[i]['lon']],
        popup=f"{df_mapa_fraude.iloc[i]['city']}: ${df_mapa_fraude.iloc[i]['amt']}"
    ).add_to(m)

# Mostrar el mapa
m
Out[14]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [15]:
#No me gusta el resultados, voy a crear un nuevo dataframe agrupando los valores de fraude por lugar
In [16]:
df_agrupado_por_ciudad = df_mapa_fraude.groupby('city', as_index=False).agg({
    'lat': 'mean',  
    'lon': 'mean',  
    'amt': 'sum' ,
})

# Mostramos el nuevo DataFrame agrupado
print(df_agrupado_por_ciudad)
           city        lat         lon      amt
0         Adams  43.651543  -89.477159  8118.71
1         Afton  45.288029  -84.342338  3959.95
2         Akron  40.748093  -81.392258  7182.18
3     Allentown  32.947180  -83.064024  7934.88
4       Andrews  40.572648  -85.763330  1002.07
..          ...        ...         ...      ...
210  Whittemore  43.029393  -94.357829  6515.12
211    Williams  38.938819  -87.053013  6805.61
212      Wilton  47.304185 -100.965209  5895.06
213   Woodville  34.432984  -85.934894  2194.65
214     Zavalla  30.780026  -94.343175  6601.45

[215 rows x 4 columns]
In [17]:
#Aca me doy soporte con ChatGPT v4.0, ya que estoy descubriendo folium

m = folium.Map(location=[df_agrupado_por_ciudad['lat'].mean(), df_agrupado_por_ciudad['lon'].mean()], zoom_start=5)
min_amount = df_agrupado_por_ciudad['amt'].min()
max_amount = df_agrupado_por_ciudad['amt'].max()
min_radius = 5
max_radius = 50

for _, row in df_agrupado_por_ciudad.iterrows():
    # Escalando el monto para que esté dentro del rango de los radios
    scaled_radius = (row['amt'] - min_amount) / (max_amount - min_amount) * (max_radius - min_radius) + min_radius
    
    # Creando un CircleMarker
    folium.CircleMarker(
        location=[row['lat'], row['lon']],
        radius=scaled_radius,  # El radio es una función del monto 'amt'
        color='blue',
        fill=True,
        fill_color='blue',
        popup=f"{row['city']}: ${row['amt']}"
    ).add_to(m)
m
Out[17]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [18]:
#No me funciona, voy a agrupar por la variable "State"
In [19]:
df_agrupado_por_estado = df_mapa_fraude.groupby('state', as_index=False).agg({
    'lat': 'mean',  
    'lon': 'mean',  
    'amt': 'sum'    
})
print(df_agrupado_por_estado)
   state        lat         lon       amt
0     AK  55.432806 -133.028497  11641.22
1     AL  32.706312  -86.767262  36474.51
2     AR  35.591582  -92.969613  16605.22
3     AZ  33.498572 -112.213427  14119.83
4     CA  36.212457 -119.937043  34995.06
5     CO  39.673001 -104.817054    150.04
6     CT  41.680095  -72.780689  17977.25
7     DC  39.101818  -76.930992   6640.64
8     FL  28.734110  -82.968836  22734.52
9     GA  32.124854  -83.399697  33619.50
10    HI  20.167208 -155.648136   6164.72
11    IA  41.809060  -93.213834  34808.15
12    ID  45.053348 -115.081530  10548.17
13    IL  40.339402  -89.405058  35657.45
14    IN  39.552824  -86.364183  34953.10
15    KS  38.872652  -97.876094  24870.42
16    KY  37.623277  -85.468882  42175.29
17    LA  30.514724  -90.873535  10249.12
18    MA  41.970681  -72.714651   6600.80
19    MD  39.131267  -77.020757  25470.69
20    ME  44.516800  -69.011901   9152.98
21    MI  43.709096  -84.265360  37753.48
22    MN  45.875844  -95.054465  36080.51
23    MO  39.061321  -93.485982  38223.18
24    MS  32.831213  -90.322636  31010.02
25    MT  47.448941 -109.869775  17561.53
26    NC  35.979486  -79.477355  20113.62
27    ND  47.477494  -98.664210  14409.83
28    NE  41.206539  -98.480538  19340.76
29    NH  43.236455  -71.785006  11118.66
30    NJ  39.850956  -74.718251  25654.85
31    NM  34.431899 -105.919478  23867.97
32    NY  41.970119  -75.244046  99746.68
33    OH  40.518876  -82.132474  23080.46
34    OK  35.389007  -97.737465  26992.48
35    OR  45.236238 -122.501386  22799.97
36    PA  40.409349  -78.812825  62807.61
37    SC  34.369078  -81.988648  15078.28
38    SD  45.533922 -100.076234  10003.97
39    TN  35.069858  -89.589109   7921.02
40    TX  32.248975  -97.774535  52310.40
41    VA  38.405318  -77.694366  41752.78
42    WA  47.597766 -121.400206  15593.19
43    WI  43.858224  -89.478336  40039.48
44    WY  42.079091 -104.963533   4455.27
In [20]:
#ya entiendo como funciona, acá sigo la receta anterior que me brindó la IA
m = folium.Map(location=[df_agrupado_por_estado['lat'].mean(), df_agrupado_por_estado['lon'].mean()], zoom_start=4)
min_radius = 5
max_radius = 50
min_amt = df_agrupado_por_estado['amt'].min()
max_amt = df_agrupado_por_estado['amt'].max()

for index, row in df_agrupado_por_estado.iterrows():
    if max_amt != min_amt: 
        scaled_radius = (row['amt'] - min_amt) / (max_amt - min_amt) * (max_radius - min_radius) + min_radius
    else:
        scaled_radius = max_radius
    folium.CircleMarker(
        location=[row['lat'], row['lon']],
        radius=scaled_radius,
        color='red',
        fill=True,
        fill_color='pink',
        popup=f"{row['state']}: ${row['amt']}"
    ).add_to(m)
m
Out[20]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Conclusiones preliminares:

  • Parece haber una mayor concentración de transacciones fraudulentas, o al menos de montos más grandes de transacciones fraudulentas, en la parte este de los Estados Unidos. Es notable la concentración alrededor de la región del Atlántico Medio y el Noreste.
  • Algunos estados tienen círculos relativamente pequeños, lo que sugiere que el número o el monto de las transacciones fraudulentas en esos lugares es menor en comparación con otros estados. Esto podría deberse a diferentes factores, como una menor población, menos actividad comercial o mejores medidas de prevención del fraude.
  • Algunos de los círculos más grandes están ubicados cerca de lo que parecen ser importantes centros urbanos, como Los Ángeles y Nueva York. Esto podría indicar que hay una correlación entre la actividad de fraude y la densidad de población o el volumen de transacciones comerciales.
In [21]:
#Evaluando a los merchant
In [22]:
df_fraude.head(3)
Out[22]:
Unnamed: 0 trans_date_trans_time cc_num merchant category amt first last gender street ... lat long city_pop job dob trans_num unix_time merch_lat merch_long is_fraud
1685 1685 21/06/2020 22:06 3.560730e+15 fraud_Hamill-D'Amore health_fitness 24.84 Brooke Smith F 63542 Luna Brook Apt. 012 ... 31.8599 -102.7413 23 Cytogeneticist 15/09/1969 16bf2e46c54369a8eab2214649506425 1371852399 32.575873 -102.604290 1
1767 1767 21/06/2020 22:32 6.564460e+15 fraud_Rodriguez, Yost and Jenkins misc_net 780.52 Douglas Willis M 619 Jeremy Garden Apt. 681 ... 42.5545 -90.3508 1306 Public relations officer 10/09/1958 ab4b379d2c0c9c667d46508d4e126d72 1371853942 42.461127 -91.147148 1
1781 1781 21/06/2020 22:37 6.564460e+15 fraud_Nienow PLC entertainment 620.33 Douglas Willis M 619 Jeremy Garden Apt. 681 ... 42.5545 -90.3508 1306 Public relations officer 10/09/1958 47a9987ae81d99f7832a54b29a77bf4b 1371854247 42.771834 -90.158365 1

3 rows × 23 columns

In [23]:
merchant_sums = df_fraude.groupby('merchant')['amt'].sum() #analizando los vendedores por montos
mean_amt = merchant_sums.mean()
std_amt = merchant_sums.std()
xmin, xmax = merchant_sums.min(), merchant_sums.max()
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, mean_amt, std_amt)
plt.hist(merchant_sums, bins=30, density=True, alpha=0.6, color='red')
plt.plot(x, p, 'k', linewidth=2)

title_text = 'Distribución del Monto total perdido por Comerciante'
plt.title(title_text)
plt.xlabel('Monto')
plt.ylabel('Densidad')
plt.show()
No description has been provided for this image
In [24]:
#haciendo zoom al monto, hay una concentración gigante entre 0 y 2500
In [25]:
merchant_sums = df_fraude.groupby('merchant')['amt'].sum().reset_index()
filtered_merchant_sums = merchant_sums[merchant_sums['amt'] <= 2500]['amt']
mean_amt = filtered_merchant_sums.mean()
std_amt = filtered_merchant_sums.std()
xmin, xmax = filtered_merchant_sums.min(), filtered_merchant_sums.max()
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, mean_amt, std_amt)
plt.hist(filtered_merchant_sums, bins=30, density=True, alpha=0.6, color='g')
plt.plot(x, p, 'k', linewidth=2)

title_text = 'Monto por comerciante menor a 2500 (total fraude)'
plt.title(title_text)
plt.xlabel('Monto')
plt.ylabel('Densidad')

# Mostrar la gráfica
plt.show()
No description has been provided for this image
In [31]:
merchant_sums = df_fraude.groupby('merchant')['amt'].sum().reset_index()
filtered_merchant_sums = merchant_sums[merchant_sums['amt'] <= 500]['amt']
mean_amt = filtered_merchant_sums.mean()
std_amt = filtered_merchant_sums.std()
xmin, xmax = filtered_merchant_sums.min(), filtered_merchant_sums.max()
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, mean_amt, std_amt)
plt.hist(filtered_merchant_sums, bins=30, density=True, alpha=0.6, color='g')
plt.plot(x, p, 'k', linewidth=2)
title_text = 'Distribución del Monto Agrupado por Comerciante (menor a un total de 500)'
plt.title(title_text)
plt.xlabel('Monto')
plt.ylabel('Densidad')
plt.show()
No description has been provided for this image
In [32]:
merchant_sums = df_fraude.groupby('merchant')['amt'].sum().reset_index()
filtered_merchant_sums = merchant_sums[merchant_sums['amt'] <= 150]['amt']
mean_amt = filtered_merchant_sums.mean()
std_amt = filtered_merchant_sums.std()
xmin, xmax = filtered_merchant_sums.min(), filtered_merchant_sums.max()
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, mean_amt, std_amt)
plt.hist(filtered_merchant_sums, bins=30, density=True, alpha=0.6, color='g')
plt.plot(x, p, 'k', linewidth=2)
title_text = 'Distribución del Monto Agrupado por Comerciante (menor a un total de 150)'
plt.title(title_text)
plt.xlabel('Monto Total')
plt.ylabel('Densidad')
plt.show()
No description has been provided for this image
In [28]:
#voy a cambiar a un histograma acumulado para entender el % 
In [29]:
merchant_sums = df_fraude.groupby('merchant')['amt'].sum().reset_index()
filtered_merchant_sums = merchant_sums[merchant_sums['amt'] <= 150]['amt']
quartiles = np.percentile(filtered_merchant_sums, [25, 50, 75])
plt.hist(filtered_merchant_sums, bins=200, cumulative=True, alpha=0.6, color='g')
for quartile in quartiles:
    plt.axvline(quartile, color='r', linestyle='dashed', linewidth=1)
plt.text(quartiles[0], plt.gca().get_ylim()[1]*0.9, "Q1", horizontalalignment='center', color='red')
plt.text(quartiles[1], plt.gca().get_ylim()[1]*0.9, "Q2 (Mediana)", horizontalalignment='center', color='red')
plt.text(quartiles[2], plt.gca().get_ylim()[1]*0.9, "Q3", horizontalalignment='center', color='red')
plt.title('Histograma Acumulado')
plt.xlabel('Monto Total')
plt.ylabel('Frecuencia Acumulada')
plt.show()
No description has been provided for this image

Análisis inicial

  • La mayoría de los montos agrupados por comerciante son relativamente bajos, dado que la mediana (Q2) está cerca del 20, y el Q3 no está muy lejos del Q2, indicando que el 75% de los comerciantes tiene montos de fraude que se acumulan hasta aproximadamente 40 o menos. Esto podría indicar que los fraudes más significativos (en términos de monto) son cometidos por un número menor de comerciantes.
  • Dado que Q3 está más cerca de Q2 que de Q1 (no se muestra por lo que debe estar muy cerca del 0), la distribución parece estar sesgada hacia la izquierda, lo que indica que hay unos pocos casos con montos de fraude muy altos, mientras que la mayoría de los comerciantes tienen montos de fraude menores.
  • El histograma sube rápidamente al principio y luego se aplana, lo que sugiere que hay un pequeño número de comerciantes con montos de fraude muy altos que contribuyen significativamente al monto total de fraude
In [ ]: